package com.factory.aiclient.webSocket;

import com.factory.common.utils.DateUtil;
import com.factory.common.utils.ImgUtil;
import com.factory.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import javax.validation.constraints.NotNull;
import javax.websocket.Session;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket管理
 */
@Slf4j
public class VideoManager {

    /**
     * 客户端连接session集合 <sessionID,cameraID></>
     */
    private static Map<String, String> writerOfCameraId = new ConcurrentHashMap<String, String>();

    /**
     * 客户端连接session集合 <cameraId,Session></>
     */
    private static Map<String, Session> writers = new ConcurrentHashMap<>();

    /**
     * 客户端连接session集合 <SessionId,Base64ImageReader></>
     */
    private static Map<String, Base64ImageReader> readers = new ConcurrentHashMap<>();

    /**
     * reader 需要的 writer 数量集合 <cameraId,number></>
     */
    private static Map<String, Integer> writerForReaderNumber = new ConcurrentHashMap<>();

    /**
     * 增加数量
     *
     * @param cameraId
     * @return
     */
    public static Integer addWriterForReaderNumber(String cameraId) {
        Integer numbers = writerForReaderNumber.get(cameraId);
        if (null == numbers) {
            numbers = 1;
            writerForReaderNumber.put(cameraId, numbers);
        } else
            numbers++;

        return numbers;
    }

    /**
     * 减少数量
     *
     * @param cameraId
     * @return
     */
    public static Integer subWriterForReaderNumber(String cameraId) {
        Integer numbers = writerForReaderNumber.get(cameraId);

        if (null == numbers)
            return 0;
        else
            numbers--;

        return numbers;
    }

    public static void setWriter(String cameraId, Session session) {
        writers.put(cameraId, session);
        writerOfCameraId.put(session.getId(), cameraId);
    }

    /**
     * 存放reader的集合对象
     *
     * @param sessionId
     * @param base64ImageReader
     */
    public static void setReader(String sessionId, Base64ImageReader base64ImageReader) {
        readers.put(sessionId, base64ImageReader);
    }

    public static String getCameraId(String sessionId) {
        return writerOfCameraId.get(sessionId);
    }

    /**
     * 移除session,当时writer关闭时或者发生异常时
	 * 当时reader关闭时或者发生异常时，同时没有reader读取writer,将关闭writer
     *
     * @param session
     */
    public static void removeSession(Session session) {

        // 当时writer关闭时或者发生异常时
        writerOfCameraId.remove(session.getId());

        writers.forEach((k, v) -> {
            if (session.getId().equals(session.getId())) {
                writers.remove(k);
            }
        });

        // 当时reader关闭时或者发生异常时
        Base64ImageReader base64ImageReader = readers.remove(session.getId());
        if (null != base64ImageReader) {
            base64ImageReader.stop();

            if (0 >= subWriterForReaderNumber(base64ImageReader.getCameraId())) {
                log.info("没有reader读取writer,将关闭writer");
                //保存图片
                String read = VideoPool.read(base64ImageReader.getCameraId());
                if(StringUtil.notEmpty(read)){
                    String picturePath = "/var/project/upload/cameras/",fileName =  base64ImageReader.getCameraId()+ ".jpg";
                    ImgUtil.generateBase64Image(read, picturePath , fileName);
                }
                removeWriter(base64ImageReader.getCameraId());
            }
        }
    }

    /**
     * 移除writer
     *
     * @param cameraId
     */
    public static void removeWriter(@NotNull String cameraId) {

        Session session = writers.remove(cameraId);
        if(null != session){
			try {
				session.close();
			} catch (IOException e) {
				log.error("移除writer发生异常,{}", e);
			}
		}

        writerOfCameraId.forEach((sessionID, cameraID) -> {
			if(cameraId.equals(cameraID)){
				writerOfCameraId.remove(sessionID);
			}
        });

    }

    /**
     * 检查是否含有writer
     *
     * @param cameraId
     */
    public static Boolean hasWriter(String cameraId) {
        Collection<String> values = writerOfCameraId.values();
        Iterator<String> iterator = values.iterator();
        while (iterator.hasNext()) {
            if (cameraId.equals(iterator.next()))
                return true;
        }
        return false;
    }
}